const POPUP_SCROLL_TIME = 0.10; // seconds
const POPUP_FADE_TIME = 0.1; // seconds
+const APP_ICON_HOVER_TIMEOUT = 750; // milliseconds
+
const DISABLE_HOVER_TIMEOUT = 500; // milliseconds
const THUMBNAIL_DEFAULT_SIZE = 256;
this._thumbnailTimeoutId = 0;
this._motionTimeoutId = 0;
+ this.thumbnailsVisible = false;
+
// Initially disable hover so we ignore the enter-event if
// the switcher appears underneath the current pointer location
this._disableHover();
this.actor.connect('button-press-event', Lang.bind(this, this._clickedOutside));
this.actor.connect('scroll-event', Lang.bind(this, this._onScroll));
- this._appSwitcher = new AppSwitcher(apps);
+ this._appSwitcher = new AppSwitcher(apps, this);
this.actor.add_actor(this._appSwitcher.actor);
this._appSwitcher.connect('item-activated', Lang.bind(this, this._appActivated));
this._appSwitcher.connect('item-entered', Lang.bind(this, this._appEntered));
},
_destroyThumbnails : function() {
- Tweener.addTween(this._thumbnails.actor,
+ let thumbnailsActor = this._thumbnails.actor;
+ Tweener.addTween(thumbnailsActor,
{ opacity: 0,
time: THUMBNAIL_FADE_TIME,
transition: 'easeOutQuad',
- onComplete: function() { this.destroy(); }
+ onComplete: Lang.bind(this, function() {
+ thumbnailsActor.destroy();
+ this.thumbnailsVisible = false;
+ })
});
this._thumbnails = null;
},
Tweener.addTween(this._thumbnails.actor,
{ opacity: 255,
time: THUMBNAIL_FADE_TIME,
- transition: 'easeOutQuad'
+ transition: 'easeOutQuad',
+ onComplete: Lang.bind(this, function () { this.thumbnailsVisible = true; })
});
}
};
this._list.add_actor(bbox);
let n = this._items.length;
- bbox.connect('clicked', Lang.bind(this, function () {
- this._itemActivated(n);
- }));
- bbox.connect('enter-event', Lang.bind(this, function () {
- this._itemEntered(n);
- }));
+ bbox.connect('clicked', Lang.bind(this, function() { this._onItemClicked(n); }));
+ bbox.connect('enter-event', Lang.bind(this, function() { this._onItemEnter(n); }));
this._items.push(bbox);
},
+ _onItemClicked: function (index) {
+ this._itemActivated(index);
+ },
+
+ _onItemEnter: function (index) {
+ this._itemEntered(index);
+ },
+
addSeparator: function () {
let box = new St.Bin({ style_class: 'separator' });
this._separator = box;
}
};
-function AppSwitcher(apps) {
- this._init(apps);
+function AppSwitcher(apps, altTabPopup) {
+ this._init(apps, altTabPopup);
}
AppSwitcher.prototype = {
__proto__ : SwitcherList.prototype,
- _init : function(apps) {
+ _init : function(apps, altTabPopup) {
SwitcherList.prototype._init.call(this, true);
// Construct the AppIcons, sort by time, add to the popup
this._curApp = -1;
this._iconSize = 0;
+ this._altTabPopup = altTabPopup;
+ this._mouseTimeOutId = 0;
},
_getPreferredHeight: function (actor, forWidth, alloc) {
}
},
+ // We override SwitcherList's _onItemEnter method to delay
+ // activation when the thumbnail list is open
+ _onItemEnter: function (index) {
+ if (this._mouseTimeOutId != 0)
+ Mainloop.source_remove(this._mouseTimeOutId);
+ if (this._altTabPopup.thumbnailsVisible) {
+ this._mouseTimeOutId = Mainloop.timeout_add(APP_ICON_HOVER_TIMEOUT,
+ Lang.bind(this, function () {
+ this._enterItem(index);
+ }));
+ } else
+ this._itemEntered(index);
+ },
+
+ _enterItem: function(index) {
+ let [x, y, mask] = global.get_pointer();
+ let pickedActor = global.stage.get_actor_at_pos(Clutter.PickMode.ALL, x, y);
+ if (this._items[index].contains(pickedActor))
+ this._itemEntered(index);
+ },
+
// We override SwitcherList's highlight() method to also deal with
// the AppSwitcher->ThumbnailList arrows. Apps with only 1 window
// will hide their arrows by default, but show them when their